package org.example.camundaapp.bpm.service;

import com.alibaba.fastjson2.JSONException;
import com.alibaba.fastjson2.JSONObject;
import org.camunda.bpm.model.bpmn.Bpmn;
import org.camunda.bpm.model.bpmn.BpmnModelInstance;
import org.camunda.bpm.model.bpmn.instance.*;
import org.camunda.bpm.model.bpmn.instance.Process;
import org.camunda.bpm.model.bpmn.instance.bpmndi.BpmnDiagram;
import org.camunda.bpm.model.bpmn.instance.bpmndi.BpmnEdge;
import org.camunda.bpm.model.bpmn.instance.bpmndi.BpmnPlane;
import org.camunda.bpm.model.bpmn.instance.bpmndi.BpmnShape;
import org.camunda.bpm.model.bpmn.instance.dc.Bounds;
import org.camunda.bpm.model.bpmn.instance.di.Waypoint;

import java.io.File;
import java.util.UUID;

/**
 * @className: JsonToBpmnConverter2
 * @author: ZHRJ
 * @date: 2025-06-25 13:39
 * @Version: 1.0
 * @description:
 */
public class JsonToBpmnConverter2 {


    public String testCreateProcess() {
        BpmnModelInstance modelInstance = Bpmn.createEmptyModel();
        Definitions definitions = modelInstance.newInstance(Definitions.class); // 创建定义, 相当于一个容器
        definitions.setTargetNamespace("https://camunda.org/examples");
        modelInstance.setDefinitions(definitions);

        // 1. 创建流程（Process），Process相当于图纸，后续工作就是在图纸上添加节点和连线
        org.camunda.bpm.model.bpmn.instance.Process process = modelInstance.newInstance(org.camunda.bpm.model.bpmn.instance.Process.class);
        process.setId("Process_2");
        process.setName("Test Process2");
        definitions.addChildElement(process);

        // 2. 创建 DI 元素（关键新增），用于定义图形位置
        BpmnDiagram bpmnDiagram = modelInstance.newInstance(BpmnDiagram.class);
        BpmnPlane bpmnPlane = modelInstance.newInstance(BpmnPlane.class);
        bpmnPlane.setBpmnElement(process); // 关联到流程
        bpmnDiagram.addChildElement(bpmnPlane);
        definitions.addChildElement(bpmnDiagram); // 将 DI 图添加到 Definitions

        // 3. 创建流程节点（StartEvent、UserTask、EndEvent）并设置图形位置
        StartEvent startEvent = createFlowNode(modelInstance, process, bpmnPlane, "start", StartEvent.class, 100, 100, 36, 36);
        UserTask userTask = createFlowNode(modelInstance, process, bpmnPlane, "task", UserTask.class, 250, 80, 100, 80);
        EndEvent endEvent = createFlowNode(modelInstance, process, bpmnPlane, "end", EndEvent.class, 450, 100, 36, 36);

        // 4. 创建连接线并设置路径
        connectSequenceFlow(modelInstance, process, bpmnPlane, "flow1", startEvent, userTask, 136, 118, 250, 120);
        connectSequenceFlow(modelInstance, process, bpmnPlane, "flow2", userTask, endEvent, 350, 120, 450, 118);


        //Bpmn.writeModelToFile(new File("target/new-process.bpmn"), modelInstance);

        return Bpmn.convertToString(modelInstance);

    }


    /**
     * 创建流程节点并设置图形位置
     * @param modelInstance
     * @param process
     * @param bpmnPlane
     * @param nodeId
     * @param nodeClass
     * @param x
     * @param y
     * @param width
     * @param height
     * @return
     * @param <T>
     */
    private <T extends FlowNode> T createFlowNode(
            BpmnModelInstance modelInstance,
            Process process,
            BpmnPlane bpmnPlane,
            String nodeId,
            Class<T> nodeClass,
            int x, int y, int width, int height) {

        // 1、创建流程节点（StartEvent、UserTask、EndEvent）
        T node = modelInstance.newInstance(nodeClass);
        node.setId(nodeId);
        // 2、绘制到图纸上
        process.addChildElement(node);

        // 设置图形位置（BpmnShape）
        BpmnShape shape = modelInstance.newInstance(BpmnShape.class);
        shape.setBpmnElement(node);
        Bounds bounds = modelInstance.newInstance(Bounds.class);
        bounds.setX(x);
        bounds.setY(y);
        bounds.setWidth(width);
        bounds.setHeight(height);
        shape.setBounds(bounds);
        bpmnPlane.addChildElement(shape);

        return node;
    }

    /**
     * 创建连接线并设置路径
     * @param modelInstance
     * @param process
     * @param bpmnPlane
     * @param flowId
     * @param source
     * @param target
     * @param startX
     * @param startY
     * @param endX
     * @param endY
     */
    private void connectSequenceFlow(
            BpmnModelInstance modelInstance,
            Process process,
            BpmnPlane bpmnPlane,
            String flowId,
            FlowNode source,
            FlowNode target,
            int startX, int startY, int endX, int endY) {
        SequenceFlow flow = modelInstance.newInstance(SequenceFlow.class);
        flow.setId(flowId);
        flow.setSource(source);
        flow.setTarget(target);
        process.addChildElement(flow);

        // 设置连接线路径（BpmnEdge）
        BpmnEdge edge = modelInstance.newInstance(BpmnEdge.class);
        edge.setBpmnElement(flow);
        // 起点（从源节点右侧中间出发）
        Waypoint startWaypoint = modelInstance.newInstance(Waypoint.class);
        startWaypoint.setX(startX);
        startWaypoint.setY(startY);
        // 终点（到目标节点左侧中间）
        Waypoint endWaypoint = modelInstance.newInstance(Waypoint.class);
        endWaypoint.setX(endX);
        endWaypoint.setY(endY);
        edge.addChildElement(startWaypoint);
        edge.addChildElement(endWaypoint);
        bpmnPlane.addChildElement(edge);
    }
}
